package com.liuqing.www.phone.server.底层消息;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;

import com.gwsoft.server.reflect.ReflectRun;

/**
 * @author kevinbian E-mail: langzibian@yahoo.com.cn
 * @version 创建时间：2011-4-29 下午02:05:57
 * 
 */
public class DataPackReceive {
	
	private ByteArrayInputStream bis = null ;
	
	private DataInputStream dis = null ;
	
	private byte[] data ;
	
	private byte[] headerpack ;
	
//	消息头
	private DataPackHeader header = null ;
//	消息体
	private byte[] content ;
//	接收到的消息作为参数反射
	private Object[] parameter = null ;
	
	private String sid = null ;
	
//	反射方法调用结果数据
	private byte[] returnData = null ;
	
	public DataPackReceive(String sid ,byte[] data) {
		try {
			this.sid = sid ;
			this.data = data ;
			System.out.println("sid:"+sid+"。。。"+data.length);
			pack(data) ;
			objectReflect() ;
		} catch (Exception e) {
			e.printStackTrace() ;
		}
	}
	
	private void objectReflect(){
		System.out.println(header.getCmdModel().getMethod());
		Object obj = ReflectRun.newInstance().invoke(header.getCmdModel().getPack_class(), header.getCmdModel().getMethod(), parameter) ;
		if(obj != null){
			byte[] result = (byte[]) obj ;
			int resultLength = result.length ;
			byte[] hdr = header.fullHeader(header.getRes_cmdid() ,resultLength) ;
			
			returnData = new byte[resultLength + hdr.length] ;
			
			System.arraycopy(hdr, 0 , this.returnData, 0, hdr.length);
			System.arraycopy(result, 0 , this.returnData, hdr.length, result.length);
		}
	}
	
	private void pack(byte[] data)throws Exception {
		
		if(data.length < DataPackHeader.headerLength){
			throw new Exception("消息长度 小于 消息头长度") ;
		}
		
		this.headerpack = new byte[DataPackHeader.headerLength] ;
		System.arraycopy(this.data, 0 , this.headerpack, 0, DataPackHeader.headerLength);
		
		header = new DataPackHeader(this.headerpack) ;
		
		this.content = new byte[this.data.length - DataPackHeader.headerLength] ;
		System.arraycopy(this.data, DataPackHeader.headerLength , this.content, 0, this.content.length);

		if(header.getContentLength() < content.length){
			throw new Exception("消息内容长度 小于 消息头规定长度") ;
		}
		System.out.println("content:"+this.content.length);
		bis = new ByteArrayInputStream(this.content);
		System.out.println("content:"+content.length);
		dis = new DataInputStream(bis) ;
		xmlParameter() ;
	}
	
	/**
	 * 参数读取,按command.xml配置文件标记顺序
	 */
	private void xmlParameter(){
		if(header.getCmdModel().getParameter().size() == 0){
			parameter = new Object[2] ;
			parameter[0] = this.sid ;
			parameter[1] = header.getCmdModel().getReq_cmd() ;
			return ;
		}
		parameter = new Object[header.getCmdModel().getParameter().size() + 2] ;
		parameter[0] = this.sid ;
		parameter[1] = header.getCmdModel().getReq_cmd() ;
		int index = 2 ;
		for(Object param : header.getCmdModel().getParameter()){
			if(param.equals(String.class.getSimpleName())){
				parameter[index] = readString() ;
				System.out.println("接收参数:" +param.toString() +" :"+ parameter[index]);
			}else if(param.equals(Integer.class.getSimpleName())){
				parameter[index] = readInt() ;
				System.out.println("接收参数:" +param.toString() +" :"+ parameter[index]);
			}else if(param.equals(Byte.class.getSimpleName())){
				parameter[index] = readByte() ;
				System.out.println("接收参数:" +param.toString() +" :"+ parameter[index]);
			}else if(param.equals(Long.class.getSimpleName())){
				parameter[index] = readLong() ;
				System.out.println("接收参数:" +param.toString() +" :"+ parameter[index]);
			}else if(param.equals(Short.class.getSimpleName())){
				parameter[index] = readShort() ;
				System.out.println("接收参数:" +param.toString() +" :"+ parameter[index]);
			}else if(param.equals(Byte[].class.getSimpleName())){
				int length = Integer.parseInt(parameter[index -1].toString()) ;
				byte[] databyte = new byte[length] ;
				readByte(databyte) ;
				parameter[index] = databyte ;
				System.out.print("接收参数:" +param.toString() +" :");
				for (int i = 0; i < databyte.length; i++) {
					System.out.print("" +databyte[i] +",");
				}
				System.out.println();
			}
			index ++ ;
		}
		
		this.close() ;
	}
	
	public Object[] getParameter(){
		return parameter ;
	}
	
	public short readShort(){
		short read = 0 ;
		
		try {
			read = dis.readShort() ;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return read ;
	}
	
	public char readChar(){
		char read = 0 ;
		
		try {
			read = dis.readChar() ;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return read ;
	}
	
	public String readString(){
		String str = "" ;
		try {
			str = dis.readUTF() ;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return str ;
	}
	
	public int readInt(){
		int readint = 0 ;
		
		try {
			readint = dis.readInt() ;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return readint ;
	}
	
	public long readLong(){
		long readint = 0 ;
		
		try {
			readint = dis.readLong() ;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return readint ;
	}
	
	public double readDouble(){
		double read = 0 ;
		
		try {
			read = dis.readDouble() ;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return read ;
	}
	
	public float readFloat(){
		float read = 0 ;
		
		try {
			read = dis.readFloat() ;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return read ;
	}
	
	public byte readByte(){
		byte read = 0 ;
		try {
			read = dis.readByte() ;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return read ;
	}
	
	public int readByte(byte[] data){
		int read = 0 ;
		
		try {
			read = dis.read(data) ;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return read ;
	}
	
	public int readByte(byte[] data, int off, int len){
		int read = 0 ;
		try {
			read = dis.read(data ,off ,len) ;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return read ;
	}

	public DataPackHeader getHeader() {
		return header;
	}

	public void setHeader(DataPackHeader header) {
		this.header = header;
	}
	
	public void close(){
		try {
			this.bis.close() ;
			this.dis.close() ;
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public byte[] getReturnData() {
		return returnData;
	}

	public void setReturnData(byte[] returnData) {
		this.returnData = returnData;
	}
}
